﻿/*
 * 名称：基于多线程的，数据库连接测试类。
 * 简介：以住的数据库连接中，单线程会造成窗体卡死，现在做成多线程。
 *			 使用的时候先建立类，传送连接字符串，然后添加事件AfterTest的方法，最后Test即可。
 * 
 * 2011-6-17	建立类
 * 
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Threading;
using System.Windows.Forms;

namespace WindGoes6.Data
{
	public delegate void MyEvent(bool result, Exception e);

	/// <summary>
	/// 基于多线程的连接测试类，不会造成窗体卡死。
	/// </summary>
	public class MultiThreadSqlCon 
	{
		/// <summary>
		/// 测试连接的超时时间。
		/// </summary>
		public int Timeout = 3;

		/// <summary>
		/// 需要测试的连接字符串，由于网络延时，会有0.5秒左右的误差。
		/// </summary>
		public string ConnectionString;

		bool done = false;
		bool connected = false;
		DateTime dt = DateTime.Now;
		Thread t1 = null;
		Thread t2 = null;
		Exception exception;

		/// <summary>
		/// 在连接测试结束时发生的事件，参数只有一个bool型变量，表示是否连接成功。
		/// </summary>
		public event MyEvent AfterTest = null;

		/// <summary>
		/// 默认构造函数。
		/// </summary>
        public MultiThreadSqlCon()
        {

        }

		/// <summary>
		/// 使用待测试连接字符串和超时时间初始化实例。
		/// </summary>
		/// <param name="connectionString">待测试连接字符串。</param>
		/// <param name="timeout">超时时间，单位为秒。</param>
        public MultiThreadSqlCon(string connectionString, int timeout)
        {
			ConnectionString = connectionString;
			Timeout = timeout;
        }

		/// <summary>
		/// 数据库连接测试方法。
		/// </summary>
		private void ConTest()
		{
			try
			{
				SqlConnection sql = new SqlConnection(ConnectionString); 
				sql.Open();
				sql.Close();
				connected = true;
			}
			catch (Exception e1)
			{
				connected = false;
				exception = e1;
			}

			done = true;
		}
			

		/// <summary>
		/// 连接测试时的时间控件方法，超时就会自动退出。
		/// </summary>
		private void TestDealer()
		{
			while (!done)
			{
				TimeSpan ts = DateTime.Now - dt; 
				if (ts.TotalSeconds > Timeout)
				{
					connected = false; 
					done = true; 
				}
				Thread.Sleep(10);
			}

			if (AfterTest != null)
			{
				bool b = System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls;
				System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
				if (exception == null)
					exception = new Exception("连接超时，可能是服务器地址不正确。");
			 
				AfterTest(connected, exception);
				System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = b;
			}
			try
			{
				//线程的关闭需要时间，尤其是关闭测试数据库连接的线程。
				t1.Abort();
			}
			catch { }
		}

		/// <summary>
		/// 开始测试。
		/// </summary>
		public void StartTest()
		{
			done = false;
			connected = false;
			dt = DateTime.Now; 
			t1 = new Thread(new ThreadStart(ConTest));
			t1.IsBackground = true;
			t1.Start();

			t2 = new Thread(new ThreadStart(TestDealer));
			t2.IsBackground = true;
			t2.Start(); 
		}

		/// <summary>
		/// 强制停止测试。
		/// </summary>
		public void StopTest()
		{
			try
			{
				t1.Abort();
				t2.Abort();
			}
			catch { }
		}


	}
}
